from datetime import datetime
from io import BytesIO
from typing import Union
from flask import send_file
from sqlalchemy import desc
from werkzeug.security import generate_password_hash, check_password_hash
from factory import db

def to_img(col):
    if col:
        return send_file(BytesIO(col), mimetype='image/png')
    return None

def to_binary(img):
    if img:
        return img.read()
    return None

def insert(obj):
    db.session.add(obj)
    db.session.commit()

def delete(obj):
    db.session.delete(obj)
    db.session.commit()

class LikePost(db.Model):
    __tablename__ = 'like_post'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    uid = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    pid = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False)
    time = db.Column(db.DateTime, nullable=False, default=datetime.now)

    @staticmethod
    def get_by_uid(uid):
        return LikePost.query.filter_by(uid=uid).order_by(desc(LikePost.time)).all()


class LikeComment(db.Model):
    __tablename__ = 'like_comment'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    uid = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    cid = db.Column(db.Integer, db.ForeignKey('comment.id'), nullable=False)
    time = db.Column(db.DateTime, nullable=False, default=datetime.now)

    @staticmethod
    def get_by_uid(uid):
        return LikeComment.query.filter_by(uid=uid).order_by(desc(LikeComment.time)).all()


class LikeUser(db.Model):
    __tablename__ = 'like_user'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    uid = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    uid1 = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    time = db.Column(db.DateTime, nullable=False, default=datetime.now)

    @staticmethod
    def get_by_uid(uid):
        return LikeUser.query.filter_by(uid=uid).order_by(desc(LikeUser.time)).all()


class Comment(db.Model):
    __tablename__ = 'comment'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    pid = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False)
    uid = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    time = db.Column(db.DateTime, default=datetime.now, nullable=False)
    text = db.Column(db.Text)
    status = db.Column(db.Boolean, default=False)
    unpass = db.Column(db.Boolean, default=True)

    @staticmethod
    def get_by_uid(uid):
        return Comment.query.filter_by(uid=uid).order_by(desc(Comment.time)).all()

    @staticmethod
    def get_by_pid(pid):
        return Comment.query.filter_by(pid=pid).order_by(desc(Comment.time)).all()

    @staticmethod
    def get_by_status(status):
        return Comment.query.filter_by(status=status).order_by(Comment.time).all()


class Post(db.Model):
    __tablename__ = 'post'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    uid = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    sort = db.Column(db.String(50))
    text = db.Column(db.Text)
    img = db.Column(db.LargeBinary)
    status = db.Column(db.Boolean, default=False)
    unpass = db.Column(db.Boolean, default=True)
    time = db.Column(db.DateTime, nullable=False, default=datetime.now)

    @staticmethod
    def get_by_uid(uid):
        return Post.query.filter_by(uid=uid).order_by(desc(Post.time)).all()

    @staticmethod
    def get_by_sort(sort):
        return Post.query.filter_by(sort=sort).order_by(desc(Post.time)).all()

    @staticmethod
    def get_by_status(status):
        return Post.query.filter_by(status=status).order_by(Post.time).all()


class Prove(db.Model):
    __tablename__ = 'prove'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    uid = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    time = db.Column(db.DateTime, nullable=False, default=datetime.now)
    img = db.Column(db.LargeBinary)
    status = db.Column(db.Boolean, default=False)
    role = db.Column(db.String(50))
    unpass = db.Column(db.Boolean, default=True)


    @staticmethod
    def get_by_uid(uid):
        return Prove.query.filter_by(uid=uid).first()

    @staticmethod
    def get_by_status(status):
        return Prove.query.filter_by(status=status).order_by(Prove.time).all()

def unpass(obj:[Comment,Post,Prove],unpassed:bool=True):
    obj.status = True
    obj.unpass = unpassed
    insert(obj)


class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    time = db.Column(db.DateTime, nullable=False, default=datetime.now)
    username = db.Column(db.String(255), nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)
    img = db.Column(db.LargeBinary)
    text = db.Column(db.Text)
    role = db.Column(db.String(50), default='访客')

    @staticmethod
    def get_by_username(username):
        return User.query.filter_by(username=username).first()

    @staticmethod
    def get_by_uid(uid):
        return User.query.filter_by(id=uid).first()

    @staticmethod
    def register_user(username, password):
        if User.query.filter_by(username=username).first():
            return False

        new_user = User(username=username)
        new_user.password_hash = generate_password_hash(password)

        db.session.add(new_user)
        db.session.commit()
        return True

    @staticmethod
    def validate_user(username, password):
        user = User.query.filter_by(username=username).first()
        if user is None:
            return False
        if check_password_hash(user.password_hash, password):
            return True
        return False


